package com.wechat.service.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class RedisService {

    private static final Logger logger = LoggerFactory.getLogger(RedisService.class);

    @Resource(name = "redisTemplate")
    private RedisTemplate<String, ?> redisTemplate;

    /**
     * 指定指定key的过期时间（秒）
     *
     * @param key
     * @param expire
     * @return
     */
    public boolean expire(final String key, long expire) {
        try {
            return redisTemplate.expire(key, expire, TimeUnit.SECONDS);
        } catch (Exception e) {
            logger.warn("[指定指定key的过期时间异常]:", e);
            return false;
        }
    }

    /**
     * 指定key设值值(String)
     *
     * @param key
     * @param value
     * @return
     */
    public boolean set(final String key, final String value) {
        try {
            boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
                @Override
                public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                    RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                    connection.set(serializer.serialize(key), serializer.serialize(value));
                    return true;
                }
            });
            return result;
        } catch (Exception e) {
            logger.warn("[指定key设值值(String)异常]:", e);
            return false;
        }
    }

    /**
     * 获取指定key的值(list)
     *
     * @param key
     * @return
     */
    public String get(final String key) {
        try {
            String result = redisTemplate.execute(new RedisCallback<String>() {
                @Override
                public String doInRedis(RedisConnection connection) throws DataAccessException {
                    RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                    byte[] value = connection.get(serializer.serialize(key));
                    return serializer.deserialize(value);
                }
            });
            return result;
        } catch (Exception e) {
            logger.warn("[获取指定key的值(list)异常]:", e);
            return null;
        }
    }

    public <T> boolean setEntity(String key, T t) {
        try {
            String value = JSONObject.toJSONString(t);
            return set(key, value);
        } catch (Exception e) {
            logger.warn("[指定key设值值(实体)异常]:", e);
            return false;
        }
    }

    public <T> T getEntity(String key, Class<T> clz) {
        try {
            String json = get(key);
            if (json != null) {
                T t = JSON.parseObject(json, clz);
                return t;
            } else {
                return null;
            }
        } catch (Exception e) {
            logger.warn("[获取指定key的值(实体)异常]:", e);
            return null;
        }
    }

    /**
     * 指定key设值值(List)
     *
     * @param key
     * @param list
     * @param <T>
     * @return
     */
    public <T> boolean setList(String key, List<T> list) {
        try {
            String value = JSONArray.toJSONString(list);
            return set(key, value);
        } catch (Exception e) {
            logger.warn("[指定key设值值(List)异常]:", e);
            return false;
        }
    }

    /**
     * 获取指定key的值(List)
     *
     * @param key
     * @param clz
     * @param <T>
     * @return
     */
    public <T> List<T> getList(String key, Class<T> clz) {
        try {
            String json = get(key);
            if (json != null) {
                List<T> list = JSONArray.parseArray(json, clz);
                return list;
            } else {
                return Collections.emptyList();
            }
        } catch (Exception e) {
            logger.warn("[获取指定key的值(List)异常]:", e);
            return Collections.emptyList();
        }
    }

    /**
     * 数组左边追加元素
     *
     * @param key
     * @param obj
     * @return
     */
    public long lpush(final String key, Object obj) {
        try {
            final String value = JSONObject.toJSONString(obj);
            long result = redisTemplate.execute(new RedisCallback<Long>() {
                @Override
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                    long count = connection.lPush(serializer.serialize(key), serializer.serialize(value));
                    return count;
                }
            });
            return result;
        } catch (Exception e) {
            logger.warn("[数组左边追加元素异常]:", e);
            return 0;
        }
    }

    /**
     * 数组右边追加元素
     *
     * @param key
     * @param obj
     * @return
     */
    public long rpush(final String key, Object obj) {
        try {
            final String value = JSONObject.toJSONString(obj);
            long result = redisTemplate.execute(new RedisCallback<Long>() {
                @Override
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                    long count = connection.rPush(serializer.serialize(key), serializer.serialize(value));
                    return count;
                }
            });
            return result;
        } catch (Exception e) {
            logger.warn("[数组右边追加元素异常]:", e);
            return 0;
        }
    }

    /**
     * 自增key操作
     *
     * @param key
     * @return
     */
    public long incr(final String key) {
        try {
            long result = redisTemplate.execute(new RedisCallback<Long>() {
                @Override
                public Long doInRedis(RedisConnection connection) throws DataAccessException {
                    RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                    long count = connection.incr(serializer.serialize(key));
                    return count;
                }
            });
            return result;
        } catch (Exception e) {
            logger.warn("[自增key操作异常]:", e);
            return 0;
        }
    }

    /**
     * 设置HMSET
     *
     * @param key
     * @return
     */
    /*public Boolean hmset(final String key, final Map<String,Object> map) {
        try {
            boolean result = redisTemplate.execute(new RedisCallback<Boolean>() {
                @Override
                public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                    RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
                    Map<byte[], byte[]> temp = new HashMap<>();
                    for(Object o : map.keySet()){
                        byte[] k = serializer.serialize(o.toString());
                        byte[] v = serializer.serialize(map.get(o.toString()).toString());
                        temp.put(k,v);
                    }
                    connection.hMSet(serializer.serialize(key), temp);
                    return true;
                }
            });
            return result;
        } catch (Exception e) {
            logger.warn("[设置HMSET异常]:", e);
            return false;
        }
    }*/

}